#ifndef THINK_THINK_URL_H
#define THINK_THINK_URL_H

static char* think_url =
	"\n"
	"// +----------------------------------------------------------------------\n"
	"// | ThinkPHP [ WE CAN DO IT JUST THINK ]\n"
	"// +----------------------------------------------------------------------\n"
	"// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.\n"
	"// +----------------------------------------------------------------------\n"
	"// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )\n"
	"// +----------------------------------------------------------------------\n"
	"// | Author: liu21st <liu21st@gmail.com>\n"
	"// +----------------------------------------------------------------------\n"
	"\n"
	"namespace think;\n"
	"\n"
	"class Url\n"
	"{\n"
	"    // 生成URL地址的root\n"
	"    protected static $root;\n"
	"    protected static $bindCheck;\n"
	"\n"
	"    /**\n"
	"     * URL生成 支持路由反射\n"
	"     * @param string            $url 路由地址\n"
	"     * @param string|array      $vars 参数（支持数组和字符串）a=val&b=val2... [\'a\'=>\'val1\', \'b\'=>\'val2\']\n"
	"     * @param string|bool       $suffix 伪静态后缀，默认为true表示获取配置值\n"
	"     * @param boolean|string    $domain 是否显示域名 或者直接传入域名\n"
	"     * @return string\n"
	"     */\n"
	"    public static function build($url = \'\', $vars = \'\', $suffix = true, $domain = false)\n"
	"    {\n"
	"        if (false === $domain && Route::rules(\'domain\')) {\n"
	"            $domain = true;\n"
	"        }\n"
	"        // 解析URL\n"
	"        if (0 === strpos($url, \'[\') && $pos = strpos($url, \']\')) {\n"
	"            // [name] 表示使用路由命名标识生成URL\n"
	"            $name = substr($url, 1, $pos - 1);\n"
	"            $url  = \'name\' . substr($url, $pos + 1);\n"
	"        }\n"
	"        if (false === strpos($url, \'://\') && 0 !== strpos($url, \'/\')) {\n"
	"            $info = parse_url($url);\n"
	"            $url  = !empty($info[\'path\']) ? $info[\'path\'] : \'\';\n"
	"            if (isset($info[\'fragment\'])) {\n"
	"                // 解析锚点\n"
	"                $anchor = $info[\'fragment\'];\n"
	"                if (false !== strpos($anchor, \'?\')) {\n"
	"                    // 解析参数\n"
	"                    list($anchor, $info[\'query\']) = explode(\'?\', $anchor, 2);\n"
	"                }\n"
	"                if (false !== strpos($anchor, \'@\')) {\n"
	"                    // 解析域名\n"
	"                    list($anchor, $domain) = explode(\'@\', $anchor, 2);\n"
	"                }\n"
	"            } elseif (strpos($url, \'@\') && false === strpos($url, \'\\\\\')) {\n"
	"                // 解析域名\n"
	"                list($url, $domain) = explode(\'@\', $url, 2);\n"
	"            }\n"
	"        }\n"
	"\n"
	"        // 解析参数\n"
	"        if (is_string($vars)) {\n"
	"            // aaa=1&bbb=2 转换成数组\n"
	"            parse_str($vars, $vars);\n"
	"        }\n"
	"\n"
	"        if ($url) {\n"
	"            $rule = Route::name(isset($name) ? $name : $url . (isset($info[\'query\']) ? \'?\' . $info[\'query\'] : \'\'));\n"
	"            if (is_null($rule) && isset($info[\'query\'])) {\n"
	"                $rule = Route::name($url);\n"
	"                // 解析地址里面参数 合并到vars\n"
	"                parse_str($info[\'query\'], $params);\n"
	"                $vars = array_merge($params, $vars);\n"
	"                unset($info[\'query\']);\n"
	"            }\n"
	"        }\n"
	"        if (!empty($rule) && $match = self::getRuleUrl($rule, $vars)) {\n"
	"            // 匹配路由命名标识\n"
	"            $url = $match[0];\n"
	"            // 替换可选分隔符\n"
	"            $url = preg_replace([\'/(\\W)\\?$/\', \'/(\\W)\\?/\'], [\'\', \'\\1\'], $url);\n"
	"            if (!empty($match[1])) {\n"
	"                $domain = $match[1];\n"
	"            }\n"
	"            if (!is_null($match[2])) {\n"
	"                $suffix = $match[2];\n"
	"            }\n"
	"        } elseif (!empty($rule) && isset($name)) {\n"
	"            throw new \\InvalidArgumentException(\'route name not exists:\' . $name);\n"
	"        } else {\n"
	"            // 检查别名路由\n"
	"            $alias      = Route::rules(\'alias\');\n"
	"            $matchAlias = false;\n"
	"            if ($alias) {\n"
	"                // 别名路由解析\n"
	"                foreach ($alias as $key => $val) {\n"
	"                    if (is_array($val)) {\n"
	"                        $val = $val[0];\n"
	"                    }\n"
	"                    if (0 === strpos($url, $val)) {\n"
	"                        $url        = $key . substr($url, strlen($val));\n"
	"                        $matchAlias = true;\n"
	"                        break;\n"
	"                    }\n"
	"                }\n"
	"            }\n"
	"            if (!$matchAlias) {\n"
	"                // 路由标识不存在 直接解析\n"
	"                $url = self::parseUrl($url, $domain);\n"
	"            }\n"
	"            if (isset($info[\'query\'])) {\n"
	"                // 解析地址里面参数 合并到vars\n"
	"                parse_str($info[\'query\'], $params);\n"
	"                $vars = array_merge($params, $vars);\n"
	"            }\n"
	"        }\n"
	"\n"
	"        // 检测URL绑定\n"
	"        if (!self::$bindCheck) {\n"
	"            $type = Route::getBind(\'type\');\n"
	"            if ($type) {\n"
	"                $bind = Route::getBind($type);\n"
	"                if ($bind && 0 === strpos($url, $bind)) {\n"
	"                    $url = substr($url, strlen($bind) + 1);\n"
	"                }\n"
	"            }\n"
	"        }\n"
	"        // 还原URL分隔符\n"
	"        $depr = Config::get(\'pathinfo_depr\');\n"
	"        $url  = str_replace(\'/\', $depr, $url);\n"
	"\n"
	"        // URL后缀\n"
	"        $suffix = in_array($url, [\'/\', \'\']) ? \'\' : self::parseSuffix($suffix);\n"
	"        // 锚点\n"
	"        $anchor = !empty($anchor) ? \'#\' . $anchor : \'\';\n"
	"        // 参数组装\n"
	"        if (!empty($vars)) {\n"
	"            // 添加参数\n"
	"            if (Config::get(\'url_common_param\')) {\n"
	"                $vars = http_build_query($vars);\n"
	"                $url .= $suffix . \'?\' . $vars . $anchor;\n"
	"            } else {\n"
	"                $paramType = Config::get(\'url_param_type\');\n"
	"                foreach ($vars as $var => $val) {\n"
	"                    if (\'\' !== trim($val)) {\n"
	"                        if ($paramType) {\n"
	"                            $url .= $depr . urlencode($val);\n"
	"                        } else {\n"
	"                            $url .= $depr . $var . $depr . urlencode($val);\n"
	"                        }\n"
	"                    }\n"
	"                }\n"
	"                $url .= $suffix . $anchor;\n"
	"            }\n"
	"        } else {\n"
	"            $url .= $suffix . $anchor;\n"
	"        }\n"
	"        // 检测域名\n"
	"        $domain = self::parseDomain($url, $domain);\n"
	"        // URL组装\n"
	"        $url = $domain . rtrim(self::$root ?: Request::instance()->root(), \'/\') . \'/\' . ltrim($url, \'/\');\n"
	"\n"
	"        self::$bindCheck = false;\n"
	"        return $url;\n"
	"    }\n"
	"\n"
	"    // 直接解析URL地址\n"
	"    protected static function parseUrl($url, &$domain)\n"
	"    {\n"
	"        $request = Request::instance();\n"
	"        if (0 === strpos($url, \'/\')) {\n"
	"            // 直接作为路由地址解析\n"
	"            $url = substr($url, 1);\n"
	"        } elseif (false !== strpos($url, \'\\\\\')) {\n"
	"            // 解析到类\n"
	"            $url = ltrim(str_replace(\'\\\\\', \'/\', $url), \'/\');\n"
	"        } elseif (0 === strpos($url, \'@\')) {\n"
	"            // 解析到控制器\n"
	"            $url = substr($url, 1);\n"
	"        } else {\n"
	"            // 解析到 模块/控制器/操作\n"
	"            $module  = $request->module();\n"
	"            $domains = Route::rules(\'domain\');\n"
	"            if (true === $domain && 2 == substr_count($url, \'/\')) {\n"
	"                $current = $request->host();\n"
	"                $match   = [];\n"
	"                $pos     = [];\n"
	"                foreach ($domains as $key => $item) {\n"
	"                    if (isset($item[\'[bind]\']) && 0 === strpos($url, $item[\'[bind]\'][0])) {\n"
	"                        $pos[$key] = strlen($item[\'[bind]\'][0]) + 1;\n"
	"                        $match[]   = $key;\n"
	"                        $module    = \'\';\n"
	"                    }\n"
	"                }\n"
	"                if ($match) {\n"
	"                    $domain = current($match);\n"
	"                    foreach ($match as $item) {\n"
	"                        if (0 === strpos($current, $item)) {\n"
	"                            $domain = $item;\n"
	"                        }\n"
	"                    }\n"
	"                    self::$bindCheck = true;\n"
	"                    $url             = substr($url, $pos[$domain]);\n"
	"                }\n"
	"            } elseif ($domain) {\n"
	"                if (isset($domains[$domain][\'[bind]\'][0])) {\n"
	"                    $bindModule = $domains[$domain][\'[bind]\'][0];\n"
	"                    if ($bindModule && !in_array($bindModule[0], [\'\\\\\', \'@\'])) {\n"
	"                        $module = \'\';\n"
	"                    }\n"
	"                }\n"
	"            }\n"
	"            $module = $module ? $module . \'/\' : \'\';\n"
	"\n"
	"            $controller = $request->controller();\n"
	"            if (\'\' == $url) {\n"
	"                // 空字符串输出当前的 模块/控制器/操作\n"
	"                $action = $request->action();\n"
	"            } else {\n"
	"                $path       = explode(\'/\', $url);\n"
	"                $action     = array_pop($path);\n"
	"                $controller = empty($path) ? $controller : array_pop($path);\n"
	"                $module     = empty($path) ? $module : array_pop($path) . \'/\';\n"
	"            }\n"
	"            if (Config::get(\'url_convert\')) {\n"
	"                $action     = strtolower($action);\n"
	"                $controller = Loader::parseName($controller);\n"
	"            }\n"
	"            $url = $module . $controller . \'/\' . $action;\n"
	"        }\n"
	"        return $url;\n"
	"    }\n"
	"\n"
	"    // 检测域名\n"
	"    protected static function parseDomain(&$url, $domain)\n"
	"    {\n"
	"        if (!$domain) {\n"
	"            return \'\';\n"
	"        }\n"
	"        $request    = Request::instance();\n"
	"        $rootDomain = Config::get(\'url_domain_root\');\n"
	"        if (true === $domain) {\n"
	"            // 自动判断域名\n"
	"            $domain = Config::get(\'app_host\') ?: $request->host();\n"
	"\n"
	"            $domains = Route::rules(\'domain\');\n"
	"            if ($domains) {\n"
	"                $route_domain = array_keys($domains);\n"
	"                foreach ($route_domain as $domain_prefix) {\n"
	"                    if (0 === strpos($domain_prefix, \'*.\') && strpos($domain, ltrim($domain_prefix, \'*.\')) !== false) {\n"
	"                        foreach ($domains as $key => $rule) {\n"
	"                            $rule = is_array($rule) ? $rule[0] : $rule;\n"
	"                            if (is_string($rule) && false === strpos($key, \'*\') && 0 === strpos($url, $rule)) {\n"
	"                                $url    = ltrim($url, $rule);\n"
	"                                $domain = $key;\n"
	"                                // 生成对应子域名\n"
	"                                if (!empty($rootDomain)) {\n"
	"                                    $domain .= $rootDomain;\n"
	"                                }\n"
	"                                break;\n"
	"                            } elseif (false !== strpos($key, \'*\')) {\n"
	"                                if (!empty($rootDomain)) {\n"
	"                                    $domain .= $rootDomain;\n"
	"                                }\n"
	"                                break;\n"
	"                            }\n"
	"                        }\n"
	"                    }\n"
	"                }\n"
	"            }\n"
	"\n"
	"        } else {\n"
	"            if (empty($rootDomain)) {\n"
	"                $host       = Config::get(\'app_host\') ?: $request->host();\n"
	"                $rootDomain = substr_count($host, \'.\') > 1 ? substr(strstr($host, \'.\'), 1) : $host;\n"
	"            }\n"
	"            if (substr_count($domain, \'.\') < 2 && !strpos($domain, $rootDomain)) {\n"
	"                $domain .= \'.\' . $rootDomain;\n"
	"            }\n"
	"        }\n"
	"        if (false !== strpos($domain, \'://\')) {\n"
	"            $scheme = \'\';\n"
	"        } else {\n"
	"            $scheme = $request->isSsl() || Config::get(\'is_https\') ? \'https://\' : \'http://\';\n"
	"        }\n"
	"        return $scheme . $domain;\n"
	"    }\n"
	"\n"
	"    // 解析URL后缀\n"
	"    protected static function parseSuffix($suffix)\n"
	"    {\n"
	"        if ($suffix) {\n"
	"            $suffix = true === $suffix ? Config::get(\'url_html_suffix\') : $suffix;\n"
	"            if ($pos = strpos($suffix, \'|\')) {\n"
	"                $suffix = substr($suffix, 0, $pos);\n"
	"            }\n"
	"        }\n"
	"        return (empty($suffix) || 0 === strpos($suffix, \'.\')) ? $suffix : \'.\' . $suffix;\n"
	"    }\n"
	"\n"
	"    // 匹配路由地址\n"
	"    public static function getRuleUrl($rule, &$vars = [])\n"
	"    {\n"
	"        foreach ($rule as $item) {\n"
	"            list($url, $pattern, $domain, $suffix) = $item;\n"
	"            if (empty($pattern)) {\n"
	"                return [rtrim($url, \'$\'), $domain, $suffix];\n"
	"            }\n"
	"            $type = Config::get(\'url_common_param\');\n"
	"            foreach ($pattern as $key => $val) {\n"
	"                if (isset($vars[$key])) {\n"
	"                    $url = str_replace([\'[:\' . $key . \']\', \'<\' . $key . \'?>\', \':\' . $key . \'\', \'<\' . $key . \'>\'], $type ? $vars[$key] : urlencode($vars[$key]), $url);\n"
	"                    unset($vars[$key]);\n"
	"                    $result = [$url, $domain, $suffix];\n"
	"                } elseif (2 == $val) {\n"
	"                    $url    = str_replace([\'/[:\' . $key . \']\', \'[:\' . $key . \']\', \'<\' . $key . \'?>\'], \'\', $url);\n"
	"                    $result = [$url, $domain, $suffix];\n"
	"                } else {\n"
	"                    break;\n"
	"                }\n"
	"            }\n"
	"            if (isset($result)) {\n"
	"                return $result;\n"
	"            }\n"
	"        }\n"
	"        return false;\n"
	"    }\n"
	"\n"
	"    // 指定当前生成URL地址的root\n"
	"    public static function root($root)\n"
	"    {\n"
	"        self::$root = $root;\n"
	"        Request::instance()->root($root);\n"
	"    }\n"
	"}\n"
	"\n"
;
#endif